﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SPiDisplaySSD1306Lib
{
    public class SSD1306DeviceConfiguration
    {
        private SSD1306_KIND _kindOfScreen = SSD1306_KIND.SSD1306_128_32;

        public SSD1306_KIND KindOfScreen
        {
            get
            {
                return _kindOfScreen;
            }

            private set
            {
                _kindOfScreen = value;
            }
        }

        private byte _vccState = SWITCHCAPVCC;

        public byte VccState
        {
            get
            {
                return _vccState;
            }

            private set
            {
                _vccState = value;
            }
        }

        #region command

        /* Important! Uncomment the code below corresponding to your target device */

        /* Uncomment for MinnowBoard Max */
        //private const string SPI_CONTROLLER_NAME = "SPI0";  /* For MinnowBoard Max, use SPI0                            */
        //private const Int32 SPI_CHIP_SELECT_LINE = 0;       /* Line 0 maps to physical pin number 5 on the MBM          */
        //private const Int32 DATA_COMMAND_PIN = 3;           /* We use GPIO 3 since it's conveniently near the SPI pins  */
        //private const Int32 RESET_PIN = 4;                  /* We use GPIO 4 since it's conveniently near the SPI pins  */

        /* Uncomment for Raspberry Pi 2 */
        public static readonly string SPI_CONTROLLER_NAME = "SPI0";  /* For Raspberry Pi 2, use SPI0                             */
        public static readonly Int32 SPI_CHIP_SELECT_LINE = 0;       /* Line 0 maps to physical pin number 24 on the Rpi2        */
        public static readonly Int32 DATA_COMMAND_PIN = 22;          /* We use GPIO 22 since it's conveniently near the SPI pins */
        public static readonly Int32 RESET_PIN = 23;                 /* We use GPIO 23 since it's conveniently near the SPI pins */

        /* This sample is intended to be used with the following OLED display: http://www.adafruit.com/product/938 */
        public UInt32 ScreenWidthPx { get; private set; }
        public UInt32 ScreenHeigthPx { get; private set; }
        public UInt32 ScreenHeigthPages { get; private set; }
        public byte[,] DisplayBuffer { get; set; }
        public byte[] SerializedDisplayBuffer { get; set; }

        /* Display commands. See the datasheet for details on commands: http://www.adafruit.com/datasheets/SSD1306.pdf                      */
        public static readonly byte[] CMD_DISPLAY_OFF = { 0xAE };              /* Turns the display off                                    */
        public static readonly byte[] CMD_DISPLAY_ON = { 0xAF };               /* Turns the display on                                     */
        public static readonly byte[] CMD_CHARGEPUMP_ON = { 0x8D };      /* Turn on internal charge pump to supply power to display  */

        public static readonly byte[] CMD_0x80 = { 0x80 };
        public static readonly byte[] CMD_SETDISPLAYCLOCKDIV = { 0xD5 };
        public static readonly byte[] CMD_SETMULTIPLEX = { 0xA8 };
        public static readonly byte[] CMD_0x1F = { 0x1F };
        public static readonly byte[] CMD_SETDISPLAYOFFSET = { 0xD3 };
        public static readonly byte[] CMD_0x00 = { 0x00 };
        public static readonly byte[] CMD_0x02 = { 0x02 };
        public static readonly byte[] CMD_0x8F = { 0x8F };
        public static readonly byte[] CMD_0xF1 = { 0xF1 };
        public static readonly byte[] CMD_0x40 = { 0x40 };
        public static readonly byte[] CMD_0x14 = { 0x14 };
        public static readonly byte[] CMD_0x10 = { 0x10 };
        public static readonly byte[] CMD_0x22 = { 0x22 };

        public static readonly byte[] CMD_0x12 = { 0x12 };
        public static readonly byte[] CMD_0x3F = { 0x3F };
        public static readonly byte[] CMD_0x9F = { 0x9F };
        public static readonly byte[] CMD_0xCF = { 0xCF };

        public static readonly byte[] CMD_SETSTARTLINE = { 0x40 };
        public static readonly byte[] CMD_CHARGEPUMP = { 0x8D };
        public static readonly byte[] CMD_MEMORYMODE = { 0x20 };
        public static readonly byte[] CMD_SEGREMAP = { 0xA0 }; /*other possible value is { 0xA1 }; *//* Remaps the segments, which has the effect of mirroring the display horizontally */

        public static readonly byte[] CMD_SETCOMPINS = { 0xDA };
        public static readonly byte[] CMD_SETCONTRAST = { 0x81 };
        public static readonly byte[] CMD_SETPRECHARGE = { 0xd9 };
        public static readonly byte[] CMD_SETVCOMDETECT = { 0xD8 };
        public static readonly byte[] CMD_DISPLAYALLON_RESUME = { 0xA4 };
        public static readonly byte[] CMD_NORMALDISPLAY = { 0xA6 };
        public static readonly byte[] CMD_INVERTDISPLAY = { 0xA7 };


        private const byte EXTERNALVCC = 0x1;
        private const byte SWITCHCAPVCC = 0x2;

        private static readonly byte[] CMD_MEMADDRMODE = { 0x20, 0x00 };        /* Horizontal memory mode                                   */

        public static readonly byte[] CMD_COMSCANDEC = { 0xC8 };               /* Set the COM scan direction to inverse, which flips the screen vertically        */
        public static readonly byte[] CMD_COMSCANIN = { 0xC0 };
        public static readonly byte[] CMD_RESETCOLADDR = { 0x21, 0x00, 0x7F }; /* Reset the column address pointer                         */
        public static readonly byte[] CMD_RESETPAGEADDR = { 0x22, 0x00, 0x07 };/* Reset the page address pointer     */

        #endregion command

        public SSD1306DeviceConfiguration
        (
            SSD1306_KIND __kindOfScreen = SSD1306_KIND.SSD1306_128_32,
            byte __vccState = SWITCHCAPVCC,
            bool __initBuffer = true
        )
        {
            VccState = __vccState;

            switch (__kindOfScreen)
            {
                case SSD1306_KIND.SSD1306_128_32:
                    ScreenWidthPx = 128;
                    ScreenHeigthPx = 32;

                    ScreenHeigthPages = ScreenHeigthPx / 8;
                    DisplayBuffer = new byte[ScreenWidthPx, ScreenHeigthPages];
                    SerializedDisplayBuffer = new byte[ScreenWidthPx * ScreenHeigthPages];

                    break;

                case SSD1306_KIND.SSD1306_128_64:
                    ScreenWidthPx = 128;
                    ScreenHeigthPx = 64;

                    ScreenHeigthPages = ScreenHeigthPx / 8;
                    DisplayBuffer = new byte[ScreenWidthPx, ScreenHeigthPages];
                    SerializedDisplayBuffer = new byte[ScreenWidthPx * ScreenHeigthPages];

                    break;
            }


            if (__initBuffer)
            {
                InitBuffer();
            }
        }

        public void InitBuffer()
        {

            byte[] logo = new byte[] { };

            switch (KindOfScreen)
            {
                case SSD1306_KIND.SSD1306_128_32:
                    logo = new byte[] {
                        0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc
                    };
                    break;
                case SSD1306_KIND.SSD1306_128_64:
                    logo = new byte[]{
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x7f,
                        0xe0,0x0,0x40,0x0,0xc7,0xff,0x1e,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x3f,
                        0xe0,0x0,0x40,0x0,0xc1,0xff,0xe,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x37,
                        0xe0,0x0,0x40,0x0,0xc1,0xfe,0xf,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xe3,
                        0xe0,0x0,0x40,0x0,0xc0,0xfe,0xf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xe3,
                        0xe0,0x0,0x40,0x0,0xc0,0xfc,0xe,0x7f,0xf,0x23,0xc1,0xfc,0x1f,0x83,0xe0,0x40,
                        0xe0,0x0,0x40,0x0,0xc0,0xfc,0xe,0x7c,0x6,0x3,0x80,0x78,0xf,0x0,0xc0,0x0,
                        0xe0,0x0,0x40,0x0,0xc0,0x7c,0xe,0x38,0x2,0x3,0x0,0x70,0xe,0x0,0xe0,0x0,
                        0xe0,0x0,0x40,0x0,0xc0,0x78,0xe,0x38,0x7a,0xe,0x1c,0x31,0xec,0x38,0x71,0xe3,
                        0xff,0xff,0xff,0xff,0xc2,0x38,0x8e,0x30,0xfe,0x1e,0x3e,0x31,0xfc,0x7c,0x71,0xe3,
                        0xe0,0x0,0x40,0x0,0xc2,0x30,0x8e,0x31,0xfe,0x3e,0x7f,0x30,0x78,0xfc,0x71,0xe3,
                        0xe0,0x0,0x40,0x0,0xc2,0x10,0x8e,0x31,0xfe,0x3c,0x7f,0x38,0x18,0xfe,0x71,0xe3,
                        0xe0,0x0,0x40,0x0,0xc3,0x1,0x8e,0x31,0xfe,0x3c,0x7f,0x3c,0x8,0xfe,0x71,0xe3,
                        0xe0,0x0,0x40,0x0,0xc3,0x1,0x8e,0x31,0xfe,0x3c,0x3e,0x3f,0x8,0x7c,0x71,0xe3,
                        0xe0,0x0,0x40,0x0,0xc3,0x83,0x8e,0x30,0xf6,0x3e,0x1e,0x37,0x88,0x3c,0x71,0xe3,
                        0xe0,0x0,0x40,0x0,0xc3,0x83,0x8e,0x38,0x6,0x3e,0x0,0x30,0xc,0x0,0xf1,0xe0,
                        0xe0,0x0,0x40,0x0,0xc3,0xc7,0x8e,0x38,0x6,0x3f,0x0,0x70,0xe,0x0,0xf1,0xe0,
                        0xe0,0x0,0x40,0x0,0xe3,0xe7,0xce,0x3e,0x6,0x3f,0x80,0xf0,0x1f,0x1,0xf1,0xf0,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xe0,0x0,0x40,0x0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
                        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
                        };

                    break;
            }

            //TODO: this is for display a custom logo. Work in progress
            //int Index = 0;
            ///* We convert our 2-dimensional array into a serialized string of bytes that will be sent out to the display */
            //for (int PageY = 0; PageY < this.ScreenHeigthPages; PageY++)
            //{
            //    for (int PixelX = 0; PixelX < this.ScreenWidthPx; PixelX++)
            //    {
            //        this.DisplayBuffer[PixelX, PageY] = logo[Index];
            //        Index++;
            //    }
            //}



        }

        public byte[] InitCommand()
        {
            List<byte> returnArray = new List<byte>();

            switch (KindOfScreen)
            {
                case SSD1306_KIND.SSD1306_128_32:

                    returnArray.AddRange(CMD_DISPLAY_OFF);
                    returnArray.AddRange(CMD_SETDISPLAYCLOCKDIV);
                    returnArray.AddRange(CMD_0x80);
                    returnArray.AddRange(CMD_SETMULTIPLEX);
                    returnArray.AddRange(CMD_0x1F);

                    returnArray.AddRange(CMD_SETDISPLAYOFFSET);
                    returnArray.AddRange(CMD_0x00);
                    returnArray.AddRange(CMD_SETSTARTLINE);

                    returnArray.AddRange(CMD_CHARGEPUMP_ON);
                    if (VccState == EXTERNALVCC)
                    {
                        returnArray.AddRange(CMD_0x10);
                    }
                    else
                    {
                        returnArray.AddRange(CMD_0x14);
                    }

                    returnArray.AddRange(CMD_MEMORYMODE);
                    returnArray.AddRange(CMD_0x00); //Cancellare
                    returnArray.AddRange(CMD_SEGREMAP);
                    returnArray.AddRange(CMD_COMSCANIN);

                    returnArray.AddRange(CMD_SETCOMPINS);
                    returnArray.AddRange(CMD_0x02);
                    returnArray.AddRange(CMD_SETCONTRAST);
                    returnArray.AddRange(CMD_0x8F);
                    returnArray.AddRange(CMD_SETPRECHARGE);
                    if (VccState == EXTERNALVCC)
                    {
                        returnArray.AddRange(CMD_0x22);
                    }
                    else
                    {
                        returnArray.AddRange(CMD_0xF1);
                    }

                    returnArray.AddRange(CMD_SETVCOMDETECT);
                    returnArray.AddRange(CMD_0x40);
                    returnArray.AddRange(CMD_DISPLAYALLON_RESUME);
                    returnArray.AddRange(CMD_NORMALDISPLAY);
                    returnArray.AddRange(CMD_DISPLAY_ON);

                    break;

                case SSD1306_KIND.SSD1306_128_64:

                    returnArray.AddRange(CMD_DISPLAY_OFF);
                    returnArray.AddRange(CMD_SETDISPLAYCLOCKDIV);
                    returnArray.AddRange(CMD_0x80);
                    returnArray.AddRange(CMD_SETMULTIPLEX);
                    returnArray.AddRange(CMD_0x3F);

                    returnArray.AddRange(CMD_SETDISPLAYOFFSET);
                    returnArray.AddRange(CMD_0x00);
                    returnArray.AddRange(CMD_SETSTARTLINE);

                    returnArray.AddRange(CMD_CHARGEPUMP_ON);
                    if (VccState == EXTERNALVCC)
                    {
                        returnArray.AddRange(CMD_0x10);
                    }
                    else
                    {
                        returnArray.AddRange(CMD_0x14);
                    }

                    returnArray.AddRange(CMD_MEMORYMODE);
                    returnArray.AddRange(CMD_0x00); 
                    returnArray.AddRange(CMD_SEGREMAP);
                    returnArray.AddRange(CMD_COMSCANIN);

                    returnArray.AddRange(CMD_SETCOMPINS);
                    returnArray.AddRange(CMD_0x12);
                    returnArray.AddRange(CMD_SETCONTRAST);
                    if (VccState == EXTERNALVCC)
                    {
                        returnArray.AddRange(CMD_0x9F);
                    }
                    else
                    {
                        returnArray.AddRange(CMD_0xCF);
                    }
                    returnArray.AddRange(CMD_SETPRECHARGE);
                    if (VccState == EXTERNALVCC)
                    {
                        returnArray.AddRange(CMD_0x22);
                    }
                    else
                    {
                        returnArray.AddRange(CMD_0xF1);
                    }

                    returnArray.AddRange(CMD_SETVCOMDETECT);
                    returnArray.AddRange(CMD_0x40);
                    returnArray.AddRange(CMD_DISPLAYALLON_RESUME);
                    returnArray.AddRange(CMD_NORMALDISPLAY);
                    returnArray.AddRange(CMD_DISPLAY_ON);

                    break;
                 
            }

            return returnArray.ToArray();
        }


        public void ClearDisplayBuf()
        {
            Array.Clear(DisplayBuffer, 0, DisplayBuffer.Length);
        }
    }

    public enum SSD1306_KIND
    {
        SSD1306_128_64,
        SSD1306_128_32
    }
}
